AWS SAM Lambda関数だけを単体でデプロイしたいときのテンプレート設定例
AWS SAM(Serverless Application Model)を利用してAPI Gateway + Lambdaなどのリソース一式をデプロイすることはよくあるかと思います。理由あって他のリソースに一切紐付かない単体のLambda関数をデプロイする機会がありましたのでテンプレートの例を紹介します。
Lambda単体が必要ならマネージメントコンソールから作成した方が早いのでは?というのは至極当然のご意見なのですが、検証の都合SAMから生み出す必要がありました。
実行環境
$ sam --version SAM CLI, version 1.36.0
本検証で利用したコード一式は以下に置いてあります。
初期設定
sam init
コマンドでHello World Example
のサンプルテンプレートで初期化しました。
$ sam init Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1 What package type would you like to use? 1 - Zip (artifact is a zip uploaded to S3) 2 - Image (artifact is an image uploaded to an ECR image repository) Package type: 1 Which runtime would you like to use? 1 - nodejs14.x 2 - python3.9 3 - ruby2.7 4 - go1.x 5 - java11 6 - dotnetcore3.1 7 - nodejs12.x 8 - nodejs10.x 9 - python3.8 10 - python3.7 11 - python3.6 12 - python2.7 13 - ruby2.5 14 - java8.al2 15 - java8 16 - dotnetcore2.1 Runtime: 2 Project name [sam-app]: lambda-alone Cloning from https://github.com/aws/aws-sam-cli-app-templates AWS quick start application templates: 1 - Hello World Example 2 - EventBridge Hello World 3 - EventBridge App from scratch (100+ Event Schemas) 4 - Step Functions Sample App (Stock Trader) 5 - Elastic File System Sample App Template selection: 1 ----------------------- Generating application: ----------------------- Name: lambda-alone Runtime: python3.9 Architectures: x86_64 Dependency Manager: pip Application Template: hello-world Output Directory: . Next application steps can be found in the README file at ./lambda-alone/README.md Commands you can use next ========================= [*] Create pipeline: cd lambda-alone && sam pipeline init --bootstrap [*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch
Lambda単体をデプロイするまで
サンプルのテンプレートをベースにテンプレートの修正と、関数を編集してAWSへデプロイしてみます。
テンプレート修正
Events:
のType: API
でAPI Gatewayと連携する設定が入っています。何も紐付けたくないLambdaの場合はEvetns:
以下を削除すればOKです。あとはEvents
に関連したOutput
があるので忘れずに削除。
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > hellow-sample Sample SAM Template for hellow-sample # More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst Globals: Function: Timeout: 3 Resources: HelloWorldFunction: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: hello_world/ Handler: app.lambda_handler Runtime: python3.9 Architectures: - x86_64 Events: HelloWorld: Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api Properties: Path: /hello Method: get Outputs: # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function # Find out more about other implicit resources you can reference within SAM # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api HelloWorldApi: Description: "API Gateway endpoint URL for Prod stage for Hello World function" Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/" HelloWorldFunction: Description: "Hello World Lambda Function ARN" Value: !GetAtt HelloWorldFunction.Arn HelloWorldFunctionIamRole: Description: "Implicit IAM Role created for Hello World function" Value: !GetAtt HelloWorldFunctionRole.Arn
変更箇所
少し手直してシンプルなテンプレートにしました。
FunctionName:
を追加しLambda関数名を任意の名前に設定arm64
Graviton2を採用Events:
の丸ごと削除CodeUri
のディレクトリ名を変更Outputs
でEvents
内のAPI Gatewayに関する出力内容があっため削除
AWSTemplateFormatVersion: "2010-09-09" Transform: AWS::Serverless-2016-10-31 Description: > lambda-alone Sample SAM Template for lambda-alone Globals: Function: Timeout: 5 Resources: Function: Type: AWS::Serverless::Function Properties: FunctionName: "lambda-alone" CodeUri: ./lambda-alone Handler: app.lambda_handler Runtime: python3.9 Architectures: - arm64 Outputs: HelloWorldFunction: Description: "Lambda Function ARN" Value: !GetAtt Function.Arn HelloWorldFunctionIamRole: Description: "Implicit IAM Role created for function" Value: !GetAtt FunctionRole.Arn
Memo
最小限のテンプレートを目指してOutputs:
の内容は欲していなかったので全削除しました。sam deploy
すると以下のエラーのメッセージが表示されました。SAMのテンプレートはOutput
がnull
になることを許さないことを知りました。
Error: Failed to create changeset for the stack: lambda-test, ex: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state: For expression "Status" we matched expected path: "FAILED" Status: FAILED. Reason: [/Outputs] 'null' values are not allowed in templates
sam local start-lambda
コマンドでローカルのエンドポイントから呼び出せるのか試してみました。
$ sam local start-lambda Starting the Local Lambda Service. You can now invoke your Lambda Functions defined in your template through the endpoint. 2021-12-04 11:55:45 * Running on http://127.0.0.1:3001/ (Press CTRL+C to quit) 2021-12-04 11:55:57 127.0.0.1 - - [04/Dec/2021 11:55:57] "GET / HTTP/1.1" 404 -
API Gatewayも何もないのでLambdaを呼び出しようがないですよね。
$ curl http://127.0.0.1:3001/ {"Type": "LocalService", "Message": "PathNotFoundException"}⏎
sam local invoke
コマンドでLambdaを呼べるか試してみます。こちらはLambdaを実行して意図したレスポンスが返ってきました。
$ sam local invoke ...snip... REPORT RequestId: 090ff64d-7513-43b5-8594-a4150280d2af Init Duration: 3.18 ms Duration: 1342.88 ms Billed Duration: 1343 msMemory Size: 128 MB Max Memory Used: 128 MB {"statusCode": 200, "body": "{\"message\": \"Welcome to ABASHIRI city.\"}"}⏎ ...snip...
Build & Deploy
ビルドしてデプロイします。
$ sam build Building codeuri: /Users/ohmura.yasutaka/aws/ohmura.yasutaka/work/sam/targetgroup-lambda/lambda-alone/lambda-alone runtime: python3.9 metadata: {} architecture: arm64 functions: ['Function'] requirements.txt file not found. Continuing the build without dependencies. Running PythonPipBuilder:CopySource Build Succeeded Built Artifacts : .aws-sam/build Built Template : .aws-sam/build/template.yaml Commands you can use next ========================= [*] Invoke Function: sam local invoke [*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch [*] Deploy: sam deploy --guided
初回のデプロイなのでガイドに従い設定してデプロイします。
$ sam deploy --guided ...snip... Setting default arguments for 'sam deploy' ========================================= Stack Name [sam-app]: lambda-alone AWS Region [ap-northeast-1]: #Shows you resources changes to be deployed and require a 'Y' to initiate deploy Confirm changes before deploy [y/N]: y #SAM needs permission to be able to create roles to connect to the resources in your template Allow SAM CLI IAM role creation [Y/n]: y #Preserves the state of previously provisioned resources when an operation fails Disable rollback [y/N]: n Save arguments to configuration file [Y/n]: y SAM configuration file [samconfig.toml]: SAM configuration environment [default]: ...snip...
マネージメントコンソールから確認
リソースベースポリシーも何もありません。これだとテスト実行しか呼び出しようがないです。
テスト実行は成功しました。SAMから単体のLambdaをデプロイできることを確認できました。
おわりに
Lambda単体をSAMから生み出したかったのですが情報がなく「もしやそんな使い方しないからできなかったりする?」と不安になりました。普通はやらなさそうなので「できました」という結果を書き留めておきます。どなたかの不安解消につながれば幸いです。